---
title: Beste Praktiken
image: /images/user-guide/tips/light-bulb.png
---

<Frame>
  <img src="/images/user-guide/tips/light-bulb.png" alt="Header" />
</Frame>

Dieses Dokument beschreibt die besten Praktiken, die Sie beim Arbeiten am Frontend beachten sollten.

## Zustandsverwaltung

React und Recoil übernehmen die Zustandsverwaltung im Code.

### Verwenden Sie `useRecoilState`, um den Zustand zu speichern.

Es ist eine gute Praxis, so viele Atome zu erstellen, wie Sie benötigen, um Ihren Zustand zu speichern.

<Warning>

Es ist besser, zusätzliche Atome zu verwenden, als zu versuchen, zu sparsam mit Requisiten zu arbeiten.

</Warning>

```tsx
export const myAtomState = atom({
  key: 'myAtomState',
  default: 'default value',
});

export const MyComponent = () => {
  const [myAtom, setMyAtom] = useRecoilState(myAtomState);

  return (
    <div>
      <input
        value={myAtom}
        onChange={(e) => setMyAtom(e.target.value)}
      />
    </div>
  );
}
```

### Verwenden Sie `useRef` nicht, um den Zustand zu speichern.

Vermeiden Sie die Verwendung von `useRef`, um den Zustand zu speichern.

Wenn Sie den Zustand speichern möchten, sollten Sie `useState` oder `useRecoilState` verwenden.

Sehen Sie sich [an, wie Re-Renderings verwaltet werden können](#managing-re-renders), falls Sie das Gefühl haben, dass Sie `useRef` benötigen, um einige Re-Renderings zu verhindern.

## Re-Renderings verwalten

Re-Renderings können in React schwer zu verwalten sein.

Hier sind einige Regeln, die befolgt werden sollten, um unnötige Re-Renderings zu vermeiden.

Beachten Sie, dass Sie **immer** Re-Renderings vermeiden können, indem Sie deren Ursache verstehen.

### Arbeiten Sie auf der Root-Ebene

Das Vermeiden von Re-Renderings in neuen Funktionen wird jetzt erleichtert, indem sie auf Root-Ebene eliminiert werden.

Die `PageChangeEffect`-Sidecar-Komponente enthält nur eine `useEffect`, die die gesamte Logik für den Seitenwechsel enthält.

Auf diese Weise wissen Sie, dass es nur einen Ort gibt, der ein Re-Rendering auslösen kann.

### Denken Sie immer zweimal nach, bevor Sie `useEffect` in Ihre Codebasis aufnehmen.

Re-Renderings werden oft durch unnötige `useEffect`-Verwendungen verursacht.

Sie sollten überlegen, ob Sie `useEffect` benötigen oder ob Sie die Logik in eine Ereignishandlerfunktion verschieben können.

Es ist in der Regel einfach, die Logik in eine `handleClick` oder `handleChange`-Funktion zu verschieben.

Sie können sie auch in Bibliotheken wie Apollo finden: `onCompleted`, `onError`, usw.

### Verwenden Sie eine Nebekomponente, um `useEffect` oder die Datenabruflogik zu extrahieren

Wenn Sie das Gefühl haben, in Ihrer Hauptkomponente `useEffect` hinzufügen zu müssen, sollten Sie in Betracht ziehen, sie in eine Sidecar-Komponente auszulagern.

Dasselbe können Sie auch für die Datenabruflogik mit Apollo-Hooks anwenden.

```tsx
// ❌ Bad, will cause re-renders even if data is not changing, 
//    because useEffect needs to be re-evaluated
export const PageComponent = () => {
  const [data, setData] = useRecoilState(dataState);
  const [someDependency] = useRecoilState(someDependencyState);

  useEffect(() => {
    if(someDependency !== data) {
      setData(someDependency);
    }
  }, [someDependency]);

  return <div>{data}</div>;
};

export const App = () => (
  <RecoilRoot>
    <PageComponent />
  </RecoilRoot>
);
```

```tsx
// ✅ Good, will not cause re-renders if data is not changing, 
//   because useEffect is re-evaluated in another sibling component
export const PageComponent = () => {
  const [data, setData] = useRecoilState(dataState);

  return <div>{data}</div>;
};

export const PageData = () => {
  const [data, setData] = useRecoilState(dataState);
  const [someDependency] = useRecoilState(someDependencyState);

  useEffect(() => {
    if(someDependency !== data) {
      setData(someDependency);
    }
  }, [someDependency]);

  return <></>;
};

export const App = () => (
  <RecoilRoot>
    <PageData />
    <PageComponent />
  </RecoilRoot>
);
```

### Verwenden Sie Recoil-Familienstaaten und Recoil-Familienselektoren

Recoil-Familienstaaten und Selektoren sind eine großartige Möglichkeit, um Re-Renderings zu vermeiden.

Sie sind nützlich, wenn Sie eine Liste von Elementen speichern müssen.

### Sie sollten nicht `React.memo(MyComponent)` verwenden.

Vermeiden Sie die Verwendung von `React.memo()`, da es nicht die Ursache für das Re-Rendering löst, sondern stattdessen die Re-Render-Kette unterbricht, was zu unerwartetem Verhalten führen kann und es sehr schwierig macht, den Code zu refaktorisieren.

### Beschränken Sie die Nutzung von `useCallback` oder `useMemo`.

Oft sind sie nicht erforderlich und machen den Code schwerer zu lesen und zu warten für einen Leistungsgewinn, der kaum wahrnehmbar ist.

## Console.logs

`console.log`-Anweisungen bieten während der Entwicklung wertvolle Einblicke in Echtzeit in Variablewerte und den Codefluss. Aber wenn sie im Produktivcode belassen werden, kann dies zu mehreren Problemen führen:

1. **Leistung**: Übermäßiges Logging kann die Laufzeitleistung beeinflussen, insbesondere bei clientseitigen Anwendungen.

2. **Sicherheit**: Das Protokollieren sensibler Daten kann kritische Informationen offenlegen für jeden, der die Konsole des Browsers inspiziert.

3. **Sauberkeit**: Das Ausfüllen der Konsole mit Logs kann wichtige Warnungen oder Fehler verdecken, die Entwickler oder Tools sehen müssen.

4. **Professionalität**: Endbenutzer oder Kunden, die die Konsole überprüfen und eine Vielzahl von Protokollanweisungen sehen, könnten die Qualität und den Feinschliff des Codes in Frage stellen.

Stellen Sie sicher, dass Sie alle `console.logs` entfernen, bevor Sie den Code in die Produktion übertragen.

## Namensgebung

### Variablenbenennung

Variablennamen sollten die Funktion oder Funktion der Variablen genau beschreiben.

#### Das Problem mit generischen Namen

Generische Namen in der Programmierung sind nicht ideal, weil ihnen die Spezifität fehlt, was zu Mehrdeutigkeit und verminderter Lesbarkeit des Codes führt. Solche Namen vermitteln nicht den Zweck der Variablen oder Funktion, was es Entwicklern erschwert, die Absicht des Codes ohne tiefere Untersuchung zu verstehen. Dies kann zu erhöhten Debugging-Zeiten, höherer Fehleranfälligkeit und Schwierigkeiten bei der Wartung und Zusammenarbeit führen. In der Zwischenzeit macht eine beschreibende Namensgebung den Code selbsterklärend und einfacher zu navigieren, was die Codequalität und die Produktivität der Entwickler verbessert.

```tsx
// ❌ Bad, uses a generic name that doesn't communicate its
//    purpose or content clearly
const [value, setValue] = useState('');
```

```tsx
// ✅ Good, uses a descriptive name
const [email, setEmail] = useState('');
```

#### Einige Wörter, die in Variablennamen zu vermeiden sind

- Dummy

### Ereignis-Handler

Ereignis-Handler-Namen sollten mit `handle` beginnen, während `on` ein Präfix ist, das verwendet wird, um Ereignisse in Komponenten-Requisiten zu benennen.

```tsx
// ❌ Bad
const onEmailChange = (val: string) => {
  // ...
};
```

```tsx
// ✅ Good
const handleEmailChange = (val: string) => {
  // ...
};
```

## Optionale Eigenschaften

Vermeiden Sie es, den Standardwert für eine optionale Eigenschaft zu übergeben.

**BEISPIEL**

Betrachten Sie die unten definierte `EmailField`-Komponente:

```tsx
type EmailFieldProps = {
  value: string;
  disabled?: boolean;
};

const EmailField = ({ value, disabled = false }: EmailFieldProps) => (
  <TextInput value={value} disabled={disabled} fullWidth />
);
```

**Verwendung**

```tsx
// ❌ Bad, passing in the same value as the default value adds no value
const Form = () => <EmailField value="username@email.com" disabled={false} />;
```

```tsx
// ✅ Good, assumes the default value
const Form = () => <EmailField value="username@email.com" />;
```

## Komponente als Requisiten

Versuchen Sie, so viel wie möglich nicht instanziierte Komponenten als Requisiten zu übergeben, damit Kinder selbst entscheiden können, welche Requisiten sie benötigen.

Das häufigste Beispiel dafür sind Icon-Komponenten:

```tsx
const SomeParentComponent = () => <MyComponent Icon={MyIcon} />;

// In MyComponent
const MyComponent = ({ MyIcon }: { MyIcon: IconComponent }) => {
  const theme = useTheme();

  return (
    <div>
      <MyIcon size={theme.icon.size.md}>
    </div>
  )
};
```

Damit React versteht, dass die Komponente eine Komponente ist, müssen Sie PascalCase verwenden, damit sie später mit `<MyIcon>` instanziiert werden kann.

## Prop Drilling: Beschränken Sie es auf das Nötigste

Prop Drilling im React-Kontext bezieht sich auf die Praxis, Zustandvariablen und deren Setter durch viele Komponentenebenen zu leiten, auch wenn Zwischenkomponenten sie nicht verwenden. Während manchmal notwendig, kann übermäßiges Prop-Drilling führen zu:

1. **Verminderte Lesbarkeit**: Die Nachverfolgung, woher ein Prop stammt oder wo es verwendet wird, kann in einer tief verschachtelten Komponentenstruktur verworren werden.

2. **Wartungsherausforderungen**: Änderungen in der Prop-Struktur einer Komponente können Anpassungen in mehreren Komponenten erfordern, selbst wenn sie das Prop nicht direkt verwenden.

3. **Verringerte Wiederverwendbarkeit von Komponenten**: Eine Komponente, die viele Props nur zum Weiterreichen erhält, wird weniger universell und schwieriger in unterschiedlichen Kontexten wiederzuverwenden.

Wenn Sie das Gefühl haben, dass Sie übermäßiges Prop Drilling verwenden, sehen Sie sich [Best Practices für das Zustandsmanagement](#state-management).

## Importieren

Beim Importieren sollten Sie die vorgesehenen Aliase anstelle der vollständigen oder relativen Pfade verwenden.

**Die Aliase**

```js
{
  alias: {
    "~": path.resolve(__dirname, "src"),
    "@": path.resolve(__dirname, "src/modules"),
    "@testing": path.resolve(__dirname, "src/testing"),
  },
}
```

**Verwendung**

```tsx
// ❌ Bad, specifies the entire relative path
import {
  CatalogDecorator
} from '../../../../../testing/decorators/CatalogDecorator';
import {
  ComponentDecorator
} from '../../../../../testing/decorators/ComponentDecorator';
```

```tsx
// ✅ Good, utilises the designated aliases
import { CatalogDecorator } from '~/testing/decorators/CatalogDecorator';
import { ComponentDecorator } from 'twenty-ui/testing';
```

## Schemavalidierung

[Zod](https://github.com/colinhacks/zod) ist der Schema-Validator für ungetypte Objekte:

```js
const validationSchema = z
  .object({
    exist: z.boolean(),
    email: z
      .string()
      .email('Email must be a valid email'),
    password: z
      .string()
      .regex(PASSWORD_REGEX, 'Password must contain at least 8 characters'),
  })
  .required();

type Form = z.infer<typeof validationSchema>;
```

## Breaking Changes

Führen Sie immer gründliche manuelle Tests durch, bevor Sie fortfahren, um sicherzustellen, dass keine Modifikationen anderswo Störungen verursacht haben, da Testen noch nicht umfassend integriert ist.

